
package com.eworking.eim;

import org.jivesoftware.smack.AccountManager;
import org.json.JSONException;
import org.json.JSONObject;

import com.eworking.eim.broadcast.EIMHeartBeatReceiver;
import com.eworking.eim.database.EIMDatabaseManager;
import com.eworking.eim.encrypt.EIMCryptoUtils;
import com.eworking.eim.exception.EIMException;
import com.eworking.eim.group.EIMGroupManager;
import com.eworking.eim.message.EIMMessageManager;
import com.eworking.eim.user.EIMAccountUtils;
import com.eworking.eim.user.EIMUser;
import com.eworking.eim.user.EIMUserManager;
import com.eworking.eim.util.EIMLog;
import com.eworking.eim.util.PathUtil;
import com.eworking.eim.util.HttpClientRquest;
import com.eworking.eim.xmpp.XMPPConnectionManager;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.text.TextUtils;

public class EIMSessionManager {
    
    /** 日志输出标签 */
    private static final String _TAG = EIMSessionManager.class.getSimpleName();
    
    /** 上次登陆用户账号 */
    private static final String _LAST_LOGIN_ACCOUNT = "eworking.im.account";
    
    /** 上次登陆用户密码 */
    private static final String _LAST_LOGIN_PASSWORD = "eworking.im.password";
    
    private static EIMSessionManager sessionManager = null;
    
    /** XMPP服务器连接管理 */
    private XMPPConnectionManager xmppConnectionManager = null;
    
    private Context context;
    
    /** 当前登录用户对象 */
    private EIMUser currentUser = null;
    
    /** 首次登陆的时间 */
    private long firstElapsedRealtime = 0;
    
    /** 数据库管理 */
    private EIMDatabaseManager databaseManager = null;
    
    /** XMPP服务器连接心跳检测广播 */
    private EIMHeartBeatReceiver heartBeatReceiver = null;
    
    /** 心跳检测间隔时间 */
    private int heartbeatInterval = 90;
    
    /** 上次登陆用户名 -主要用于自动登陆 */
    private String lastLoginAccount;
    
    /** 上次登陆密码 - 主要用于自动登陆 */
    private String lastLoginPassword;
    
    public EIMSessionManager(Context context) {
        this.context = context;
    }
    
    public static EIMSessionManager getInstance(Context context) {
        if (sessionManager == null) {
            sessionManager = new EIMSessionManager(context);
        }
        return sessionManager;
    }
    
    /**
     * 用户登陆
     * 
     * @param account 用户账号
     * @param password 用户密码
     * @param eimCallBack
     */
    public void login(final String account, final String password, final EIMCallBack callBack) {
        // 获取企业账号
        final String JID = EIMAccountUtils.getBareJIDByAccount(account);
        EIMLog.d(_TAG, "当前登陆的企业账号：" + JID);
        
        if (isConnected()) {
            EIMLog.d(_TAG, "当前账号已经登陆");
            if (callBack != null)
                callBack.onSuccess();
            return;
        }
        
        this.currentUser = new EIMUser(JID, account);
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                try{
                	// 登录xmpp服务器
                	loginXMPPServer(JID, password);
                }catch(Exception e){
                	EIMLog.e(_TAG, "登录xmpp服务器发生异常",e);
                    if (callBack != null)
                    	callBack.onError(EIMCallBack.ERROR_EXCEPTION, e.toString());
                    return;
                }
                // 当前时间
                long currentElapsedReadtime = SystemClock.elapsedRealtime();
                // 超过24小时重新获取token令牌
                if (EIMConfig.getInstance().getAccessToken() == null || firstElapsedRealtime == 0
                    || (currentElapsedReadtime - firstElapsedRealtime) > 86400000) {
                    // 获取token令牌
                    String accessToken = getAccessToken(account, password);
                    if (TextUtils.isEmpty(accessToken)) {
                        if (callBack != null) {
                            callBack.onError(EIMCallBack.ERROR_EXCEPTION, "用户名或密码错误");
                        }
                        return;
                    }
                    try {
                        JSONObject jsonObject = new JSONObject(accessToken);
                        // token令牌
                        String token = jsonObject.getString("access_token");
                        firstElapsedRealtime = SystemClock.elapsedRealtime();
                        EIMConfig.getInstance().setAccessToken(token);
                    } catch (Exception e) {
                        if (callBack != null) {
                            callBack.onError(EIMCallBack.ERROR_EXCEPTION, "用户名或密码错误");
                        }
                    }
                }
                
                try {
                    // 初始化数据库
                    if (databaseManager == null) {
                        databaseManager = new EIMDatabaseManager(context, account);
                    }
                    // 加载所有的会话消息
                    EIMMessageManager.getInstance().loadAllConverstations();
                    // 加载所有群组
                    EIMGroupManager.getInstance().loadAllGroups();
                    // 将登陆的用户名、密码保存，主要用于自动登陆
                    setLastLoginUser(account, password);
                    // 初始化文件目录：图片、语音、视频等
                    PathUtil.getInstance().initDirs(EIMConfig.getInstance().getEntCode(), account, context);
                    //
                    EIMGroupManager.getInstance().joinGroupsAfterLogin();
                } catch (Exception e) {
                    EIMLog.e(_TAG, "登陆失败：" + account,e);
                    if (callBack != null) {
                        callBack.onError(EIMCallBack.ERROR_EXCEPTION, "登陆失败");
                    }
                }
                EIMLog.d(_TAG, "登陆XMPP服务器成功" + account);
                if (callBack != null) {
                    callBack.onSuccess();
                }
            }
        }).start();
    }
    /**
     * 登录xmpp服务
     * 
     * @param JID
     * @param password
     * @throws EIMException 连接异常
     */
    private void loginXMPPServer(String JID, String password) throws EIMException {
        if (this.xmppConnectionManager != null) {
            try {
                // 断开与XMPP服务器的连接诶
                this.xmppConnectionManager.disconnect();
            } catch (Exception e) {
                EIMLog.e(_TAG, "断开与XMPP服务器的连接");
            }
            XMPPConnectionManager.resetInstance();
            this.xmppConnectionManager = null;
        }
        this.xmppConnectionManager = new XMPPConnectionManager(JID, password, context);
        //建立连接
		this.xmppConnectionManager.connectSync();
        // 初始化用户管理
        EIMUserManager.getInstance().init(context, xmppConnectionManager);
        // 初始化EIMChatManager
        EIMChatManager.getInstance().init(context, xmppConnectionManager);
        // 初始化EIMGroupManager
        EIMGroupManager.getInstance().init(context, xmppConnectionManager);
        //登录
        this.xmppConnectionManager.loginSync();
        // 注册XMPP服务器连接检测心跳广播
        registerHeardbeatReceiver();
        // 启动XMPP服务器连接检测心跳广播
        startHeartbeatTimer();
    }
    /**
     * 退出登陆
     */
    public void logout() {
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // 停止XMPP连接检测心跳
                stopHeartbeatTimer();
                try {
                    xmppConnectionManager.disconnect();
                } catch (Exception e) {
                    EIMLog.e(_TAG, "退出登陆时，关闭XMPP连接失败:" + e.getMessage());
                }
                xmppConnectionManager = null;
                EIMLog.i(_TAG, "EaseMobChatService disconnected.");
                databaseManager.closeDatabase();
            }
        }).start();
    }
    
    /**
     * 注册XMPP服务器连接检测心跳广播
     */
    private void registerHeardbeatReceiver() {
        if (this.heartBeatReceiver != null) {
            return;
        }
        this.heartBeatReceiver = new EIMHeartBeatReceiver();
        // XMPP服务器连接检测心跳Action
        String strAction = EIMConstants._HEARDBEAT_ACTION + EIMConfig.getInstance().getEntCode();
        IntentFilter intentFilter = new IntentFilter(strAction);
        this.context.registerReceiver(this.heartBeatReceiver, intentFilter);
    }
    
    /**
     * 启动XMPP服务器连接检测心跳广播
     */
    private void startHeartbeatTimer() {
        // 定时器
        AlarmManager localAlarmManager = (AlarmManager) this.context.getSystemService(Context.ALARM_SERVICE);
        long currentElapsedRealtime = SystemClock.elapsedRealtime();
        // XMPP服务器连接检测心跳Action
        String strAction = EIMConstants._HEARDBEAT_ACTION + EIMConfig.getInstance().getEntCode();
        Intent intent = new Intent(strAction);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this.context, 0, intent, 0);
        // 按照间隔时间执行
        localAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, currentElapsedRealtime,
            this.heartbeatInterval * 1000, pendingIntent);
        EIMLog.d(_TAG, "启动XMPP连接检测心跳，间隔：" + this.heartbeatInterval);
    }
    
    /**
     * 停止XMPP连接检测心跳
     */
    private void stopHeartbeatTimer() {
        EIMLog.d(_TAG, "停止XMPP连接检测心跳");
        try {
            this.context.unregisterReceiver(this.heartBeatReceiver);
            this.heartBeatReceiver = null;
        } catch (Exception e) {
            EIMLog.e(_TAG, "停止XMPP连接检测心跳失败:" + e.getMessage());
        }
    }
    /**
     * XMPP服务器是否连接正常
     * 
     * @return
     */
    public boolean isConnected() {
        if (this.xmppConnectionManager == null) {
            return false;
        }
        return (this.xmppConnectionManager.isConnected() && this.xmppConnectionManager.isAuthentificated());
    }
    
    /**
     * 获取当前登陆用户信息
     * 
     * @return 当前登陆用户对象
     */
    public EIMUser getCurrentUser() {
        return currentUser;
    }
    
    /**
     * 获取当前登陆用户账号
     * 
     * @return
     */
    public String getCurrentLoginAccount() {
        return this.currentUser.getAccount();
    }
    
    /**
     * 获取用户令牌
     * 
     * @param account 用户账号
     * @param password 用户密码
     * @return
     */
    private String getAccessToken(String account, String password) {
    	if(account!=null)
    		return "{\"access_token\":\"123\"}";
        // 企业代码
        String entCode = EIMConfig.getInstance().getEntCode().replaceFirst("#", "/");
        String requestURL = "";
        if (EIMConfig.ARCHIVE_SERVER.contains("http://")) {
            requestURL = EIMConfig.ARCHIVE_SERVER + "/" + entCode + "/token";
        } else {
            requestURL = "http://" + EIMConfig.ARCHIVE_SERVER + "/" + entCode + "/token";
        }
        JSONObject jsonObject = new JSONObject();
        try {
            // 验证类型 - 密码验证
            jsonObject.put("grant_type", "password");
            jsonObject.put("account", account);
            jsonObject.put("password", password);
        } catch (JSONException e) {
            EIMLog.e(_TAG, "生成token令牌失败：" + e.getMessage());
        }
        String accessToken = null;
        try {
            accessToken = HttpClientRquest.post(requestURL, jsonObject.toString(), null);
        } catch (Exception e) {
            EIMLog.e(_TAG, "生成token令牌失败：" + e.getMessage());
        }
        return accessToken;
    }
    
    /**
     * 保存登陆用户账号、密码，主要用于自动登陆
     * 
     * @param account 登陆账号
     * @param password 密码
     */
    private void setLastLoginUser(String account, String password) {
        try {
            this.lastLoginAccount = account;
            this.lastLoginPassword = password;
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.context);
            SharedPreferences.Editor editor = sharedPreferences.edit();
            // 密码加密后存储
            EIMCryptoUtils cryptoUtils = EIMCryptoUtils.getInstance();
            String encryPassword = cryptoUtils.encryptBase64String(password);
            editor.putString(_LAST_LOGIN_ACCOUNT, account);
            editor.putString(_LAST_LOGIN_PASSWORD, encryPassword);
            editor.commit();
        } catch (Exception e) {
            EIMLog.e(_TAG, "保存上次登陆用户信息失败,主要用于自动登陆：" + e.getMessage());
        }
    }
    
    /**
     * 获取上次登陆的用户账号、密码，主要用于自动登陆
     * 
     * @return String[0]:用户账号、String[1]:用户密码
     */
    public String[] getLastLoginUser() {
        try {
            if (this.lastLoginAccount == null || this.lastLoginPassword == null) {
                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.context);
                this.lastLoginAccount = sharedPreferences.getString(_LAST_LOGIN_ACCOUNT, "");
                String encryPassword = sharedPreferences.getString(_LAST_LOGIN_PASSWORD, "");
                // 密码解密
                EIMCryptoUtils cryptoUtils = EIMCryptoUtils.getInstance();
                String password = cryptoUtils.decryptBase64String(encryPassword);
                this.lastLoginPassword = password;
            }
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取上次登陆用户信息失败,主要用于自动登陆：" + e.getMessage());
        }
        
        return new String[] { this.lastLoginAccount, this.lastLoginPassword };
    }
    
    /**
     * 修改密码
     * 
     * @param password 密码
     */
    public void changePasswordXMPP(String password) {
        if ((this.xmppConnectionManager != null) && (this.xmppConnectionManager.isConnected())
            && (this.xmppConnectionManager.isAuthentificated())) {
            AccountManager accountManager = this.xmppConnectionManager.getConnection().getAccountManager();
            try {
                accountManager.changePassword(password);
            } catch (Exception localException) {
                EIMLog.e("Session", "changePasswordInBackground XMPP failed: usr:" + this.currentUser.getAccount()
                    + ", newPassword:" + password + ", " + localException.toString());
            }
        }
        EIMLog.e(_TAG, "changePasswordInBackground failed. xmppConnectionManager is null. ");
    }
    
    /**
     * 创建账号
     * 
     * @param account
     * @param password
     */
    public void createAccountXMPP(String account, String password) {
        try {
            XMPPConnectionManager localXmppConnectionManager =
                new XMPPConnectionManager(account, password, this.context);
            localXmppConnectionManager.connectSync();
            AccountManager localAccountManager = localXmppConnectionManager.getConnection().getAccountManager();
            localAccountManager.createAccount(account, password);
            localXmppConnectionManager.disconnect();
            EIMLog.d("Session", "created xmpp user:" + account);
        } catch (Exception localException) {
            
        }
    }
}
